package com.gyp.utils;

import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;

import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

public class RSAUtil {
    public static final String KEY_ALGORITHM = "RSA";
    public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
    private static final String PUBLIC_KEY = "RSAPublicKey";
    //private static final String PRIVATE_KEY = "RSAPrivateKey";
    private static final String PRIVATE_KEY =
            "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDECNCmccSnKfIf\n" +
                    "pQkoEe0/stgakMY2LvQrMwzum2A+1KbVnkrHtjAGi43Ds5VOG4oEdfOhRp+YYIwh\n" +
                    "2rwwyZBCsdC1RVnRW3Ux5XoigREeVzqnu4TNS+/mnUyy/JFLu8FvGMkGAfutACBa\n" +
                    "u8ERaF4PGIsOEK+nFyFf5A58AfES3Yn++gF2ic8vYRNfi7zHCD48zmOBuhbfFvNs\n" +
                    "LTg0Hidw3QMYtqUT5pNdh+LgwIEAuF/+Eh1O9/W66Crcn5BtA3L8ztNjH+mpAaxs\n" +
                    "5D/AX7cyj8GbBY+68gCpkEgAfSNbR2YRwvhXS0sQfeqZhFjT+UaFDBaJ1p4cRP8D\n" +
                    "/+myLW1BAgMBAAECggEBAIUxOBLe2a56YXf+uenvxDKzYQErvIC0BlITrYWxLAOE\n" +
                    "mJYrpsNqldbcmsWNDrSzIWNGgPHi+iyd7JhT9elwCgRGrHd9VzlX2pi8Qe+PogHr\n" +
                    "Yn70eZbDMYyO873ovQ+n0hWZ0XuzfTxeCZ2cU+Fv9/hpxJEZ5T6yCIsOeIjpCNK3\n" +
                    "YqWOHcohw1/v+hYwiZxY1FBz53E/oKN0J+bjDMADr2EH0H0ulB0Qpg7q3S+V8cTa\n" +
                    "Dkn2Zod71CGojBh764nmuLQ78gkwnQ7g4BpUKcBqtV671Mw/i5nGfpFuSdwFgOKb\n" +
                    "cTWFyD4Z1DGZj9xy0qTeMPSbSOtTxKyIfcsV95vsv8ECgYEA55OjtddWcw+FRHT1\n" +
                    "ZsjoCDx2cQZa/6t8l9uFyfc1BRlTT3+DzAdf3YhmZuTzu6SczlKAqxAWTCrm35mL\n" +
                    "+UseEiBhouOjEwqiVFvPQgE96al4ipYoX4JBbgyv0Ki/+95KAY4QHYWFd45uYxVW\n" +
                    "UbEq5jBjQ/LtO9swaeHEWq+6fQ8CgYEA2LWQ9sMrjifXnHjUhTMwNn/5blvfCKZg\n" +
                    "EIg4YZ47AZFDsM9iZdBuaGHGElKGk7d5j86uJLZzfK/xk73s1zbDmqhtVl39N2RX\n" +
                    "KbuZ+yUHL3KMBKfXEnS+yGEx/mmWiZeA0fk3yfalzS/t2ovMnmkUWE/ORowTg41D\n" +
                    "EZJX4AoPEK8CgYEAinxoMp6MPFLTx5SKDOWonQRLcFv0n2DWKZpF7/m940a545jG\n" +
                    "IIVodvrTAkV43IYcn+YGvEXqj7I4Tw9r/bFGUmC7AsZPB1wcp4Yf88D6XXnTdE1H\n" +
                    "55XluwIrQgUoil7ssvFaAc2Pe2fZ67ce38urc+0L796esGTsFuXEntboF1ECgYAZ\n" +
                    "bn1bqB3VafGQqFFwbEhtLOmNvPRYpIXDiujq89HC5lRGTKAkiKhcUZUYE109uptm\n" +
                    "d//RySOWb2NvTiucOg4MeVWTfCY6OOlNuXlhkr/cHpo19ah0vwSgqV9flu6WqRPy\n" +
                    "EEguyGY+xTAppJxXvscncf4oI0oq9wn25vCvFx8bewKBgQCD3P+AIuKKxP38O6nG\n" +
                    "Cmj+eDoqErXKjk8wF9HJeb3w/Q4BIUbQgl8AL+E6ZqhH2/Wk++cHlFjQLdA74nJQ\n" +
                    "Ji8uHSGqi9y5fKVFoTZlm9k2MXGD/FZh1ZXIjUNl9rfgKELTngpJ/u+fQ8bLt4OO\n" +
                    "PXf+bun03ZXcqHGt0XDfBPP3Nw==\n" ;

    public RSAUtil() {
    }

    @SneakyThrows
    public static Map<String, String> createKeyPairs(Integer integer) throws Exception {
        Map<String, String> map = new HashMap();
        Security.addProvider(new BouncyCastleProvider());
        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "BC");
        generator.initialize(integer, new SecureRandom());
        KeyPair pair = generator.generateKeyPair();
        PublicKey pubKey = pair.getPublic();
        PrivateKey privKey = pair.getPrivate();
        byte[] bytepubk = pubKey.getEncoded();
        byte[] byteprik = privKey.getEncoded();
        String strpk = new String(Base64.encode(bytepubk));
        String strprivk = new String(Base64.encode(byteprik));
        map.put("pubKey", strpk);
        map.put("privKey", strprivk);
        return map;
    }

    public static String sign(byte[] data, String privateKey) throws Exception {
        byte[] keyBytes = Base64.decode(privateKey);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
        Signature signature = Signature.getInstance("MD5withRSA");
        signature.initSign(priKey);
        signature.update(data);
        return new String(Base64.encode(signature.sign()));
    }

    public static boolean verify(byte[] data, String publicKey, String sign) throws Exception {
        byte[] keyBytes = Base64.decode(publicKey);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey pubKey = keyFactory.generatePublic(keySpec);
        Signature signature = Signature.getInstance("MD5withRSA");
        signature.initVerify(pubKey);
        signature.update(data);
        return signature.verify(Base64.decode(sign));
    }

    public static byte[] decryptByPrivateKey(byte[] data, String key) throws Exception {
        byte[] keyBytes = Base64.decode(key);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(2, privateKey);
        return cipher.doFinal(data);
    }

    public static byte[] decryptByPublicKey(byte[] data, String key) throws Exception {
        byte[] keyBytes = Base64.decode(key);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        Key publicKey = keyFactory.generatePublic(x509KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(2, publicKey);
        return cipher.doFinal(data);
    }

    public static byte[] encryptByPublicKey(byte[] data, String key) throws Exception {
        byte[] keyBytes = Base64.decode(key);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        Key publicKey = keyFactory.generatePublic(x509KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(1, publicKey);
        return cipher.doFinal(data);
    }

    @SneakyThrows
    public static byte[] encryptByPrivateKey(byte[] data, String key) throws Exception {
        byte[] keyBytes = Base64.decode(key);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(1, privateKey);
        return cipher.doFinal(data);
    }

    public static String getPrivateKey(Map<String, Object> keyMap) throws Exception {
        Key key = (Key)keyMap.get("RSAPrivateKey");
        return new String(Base64.encode(key.getEncoded()));
    }

    public static String getPublicKey(Map<String, Object> keyMap) throws Exception {
        Key key = (Key)keyMap.get("RSAPublicKey");
        return new String(Base64.encode(key.getEncoded()));
    }

    public static Map<String, Object> initKey() throws Exception {
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
        keyPairGen.initialize(1024);
        KeyPair keyPair = keyPairGen.generateKeyPair();
        RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();
        Map<String, Object> keyMap = new HashMap(2);
        keyMap.put("RSAPublicKey", publicKey);
        keyMap.put("RSAPrivateKey", privateKey);
        return keyMap;
    }

    public static void main(String[] args) throws Exception {

        String privateKey =
                "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDECNCmccSnKfIf\n" +
                "pQkoEe0/stgakMY2LvQrMwzum2A+1KbVnkrHtjAGi43Ds5VOG4oEdfOhRp+YYIwh\n" +
                "2rwwyZBCsdC1RVnRW3Ux5XoigREeVzqnu4TNS+/mnUyy/JFLu8FvGMkGAfutACBa\n" +
                "u8ERaF4PGIsOEK+nFyFf5A58AfES3Yn++gF2ic8vYRNfi7zHCD48zmOBuhbfFvNs\n" +
                "LTg0Hidw3QMYtqUT5pNdh+LgwIEAuF/+Eh1O9/W66Crcn5BtA3L8ztNjH+mpAaxs\n" +
                "5D/AX7cyj8GbBY+68gCpkEgAfSNbR2YRwvhXS0sQfeqZhFjT+UaFDBaJ1p4cRP8D\n" +
                "/+myLW1BAgMBAAECggEBAIUxOBLe2a56YXf+uenvxDKzYQErvIC0BlITrYWxLAOE\n" +
                "mJYrpsNqldbcmsWNDrSzIWNGgPHi+iyd7JhT9elwCgRGrHd9VzlX2pi8Qe+PogHr\n" +
                "Yn70eZbDMYyO873ovQ+n0hWZ0XuzfTxeCZ2cU+Fv9/hpxJEZ5T6yCIsOeIjpCNK3\n" +
                "YqWOHcohw1/v+hYwiZxY1FBz53E/oKN0J+bjDMADr2EH0H0ulB0Qpg7q3S+V8cTa\n" +
                "Dkn2Zod71CGojBh764nmuLQ78gkwnQ7g4BpUKcBqtV671Mw/i5nGfpFuSdwFgOKb\n" +
                "cTWFyD4Z1DGZj9xy0qTeMPSbSOtTxKyIfcsV95vsv8ECgYEA55OjtddWcw+FRHT1\n" +
                "ZsjoCDx2cQZa/6t8l9uFyfc1BRlTT3+DzAdf3YhmZuTzu6SczlKAqxAWTCrm35mL\n" +
                "+UseEiBhouOjEwqiVFvPQgE96al4ipYoX4JBbgyv0Ki/+95KAY4QHYWFd45uYxVW\n" +
                "UbEq5jBjQ/LtO9swaeHEWq+6fQ8CgYEA2LWQ9sMrjifXnHjUhTMwNn/5blvfCKZg\n" +
                "EIg4YZ47AZFDsM9iZdBuaGHGElKGk7d5j86uJLZzfK/xk73s1zbDmqhtVl39N2RX\n" +
                "KbuZ+yUHL3KMBKfXEnS+yGEx/mmWiZeA0fk3yfalzS/t2ovMnmkUWE/ORowTg41D\n" +
                "EZJX4AoPEK8CgYEAinxoMp6MPFLTx5SKDOWonQRLcFv0n2DWKZpF7/m940a545jG\n" +
                "IIVodvrTAkV43IYcn+YGvEXqj7I4Tw9r/bFGUmC7AsZPB1wcp4Yf88D6XXnTdE1H\n" +
                "55XluwIrQgUoil7ssvFaAc2Pe2fZ67ce38urc+0L796esGTsFuXEntboF1ECgYAZ\n" +
                "bn1bqB3VafGQqFFwbEhtLOmNvPRYpIXDiujq89HC5lRGTKAkiKhcUZUYE109uptm\n" +
                "d//RySOWb2NvTiucOg4MeVWTfCY6OOlNuXlhkr/cHpo19ah0vwSgqV9flu6WqRPy\n" +
                "EEguyGY+xTAppJxXvscncf4oI0oq9wn25vCvFx8bewKBgQCD3P+AIuKKxP38O6nG\n" +
                "Cmj+eDoqErXKjk8wF9HJeb3w/Q4BIUbQgl8AL+E6ZqhH2/Wk++cHlFjQLdA74nJQ\n" +
                "Ji8uHSGqi9y5fKVFoTZlm9k2MXGD/FZh1ZXIjUNl9rfgKELTngpJ/u+fQ8bLt4OO\n" +
                "PXf+bun03ZXcqHGt0XDfBPP3Nw==\n" ;
        //String encryptStr = "k69Qbyl3ivhR/YlGtuejdDeJogfVSHJEW3TXQYfLpz04zVF3+UKltjLSYMK5kiLfazCIobukwkEwuAttaoPkbqEj+FFmqjAQBEJOwS0YPIxNl2CzMTj8OC+4wRwTe4mqJ9FzXo7Yv11Dnkpok0d4Ja8BjiSE21K/IGtRFxOa0Fo=";

        String certNo = "ifhf9cwRIIOOaZoocNHEHagT5lsvOCOq6NZcJu1U2BZ/rJwj7Z2NlhqNa2lyuwrGdOZZZAIKKPnDmWldgvTnIla8xxm9+/jbD8RvXzaY/TiG4cS+sKzNtpAq8rBwGAy6Ifc6e7TS7brCUU73ZDFNAg6enCuvfDrBGeqZtvFio3uklrUd97KWKuHCPVk4xA2tB1vySDSalNVivVokqXCY8g+N52xoAVyJB+m57n9zlfPenmhPPsOSOpzkoYTZ2L/d+qHuPJTUMB6//Ne+KBiXcByqxyAy1kKYph/ue18MrYMGU/XoAj0t0AEsx00PW8B9HcC61hl5YYw8FkNaCkwV+A==";
        String contactNum = "wnpaHfYwdILGUbpsN4leYmh/i1S7GUqIxfjNxJh9D9fhxUgy+nTNWSgsTRE9GUCXHR5hXJsDaxdUgjdb9znJRbM6IXJ4Fo+YrxE4ER2LouD5O+hgqIzqoq7PYNMOgzl6sMa73hx/kmsnDS298eJ+hxDAwlk3x0WI/dcnH8cEx7Y6HAYxHLmKh8wIk3X1yEPrOHySURjTcq5c+LPYoNSUd+rLzgwezJnveyf4CnnKM0i08ced/7i5vaDOl4nIJFWl3+hSIK5AzOHm1KEXxEoMPh0NQs5yCEppE9el0+Fuo230E978pVm4rLDAc9X9pdFJNP/bws53dvmTyUK4+fIELg==";
        String encryptStr = certNo;

        org.apache.commons.codec.binary.Base64 base64 = new org.apache.commons.codec.binary.Base64();
        byte[] byteBase64 = base64.decode(encryptStr);
        String str = new String(RSAUtil.decryptByPrivateKey(byteBase64, privateKey));

        System.out.println(str);

    }

    public static String decryRsaByPrivateKey(String encryptStr,String privatekeyStr)  {


//        if(encryptStr.length() < 25){
//            return encryptStr;
//        }

        org.apache.commons.codec.binary.Base64 base64 = new org.apache.commons.codec.binary.Base64();
        byte[] byteBase64 = base64.decode(encryptStr);
        String str = null;
        try{
            if(StringUtils.isBlank(privatekeyStr)){
                privatekeyStr = PRIVATE_KEY;
            }
            str = new String(RSAUtil.decryptByPrivateKey(byteBase64, privatekeyStr));
        }catch (Exception e){
            throw new RuntimeException(e);
        }

        return str;
    }


}
